<?php
/**
 * @file indigo/framework/classes/Request.php
 * Contains the definition for the Request class
 */
  namespace indigo\framework;
  
 /**
  * @class Request
  * Request class that provides an interface to user inputs from superglobals
  *
  * Provides initial null byte sanitation the $_POST, $_GET, $_COOKIE, and $_FILES superglobals
  *  and provides the only way to access these variables
  */
  class Request
  {
   /**
    * Static instance of the Request class
    */
    private static $_instance = NULL;
    
   /**
    * @name Superglobals
    * These contain copies of their respective superglobal counterparts
    */
   /**@{*/
    private $_post = array(); //!< $_POST counterpart
    private $_get = array(); //!< $_GET counterpart
    private $_cookie = array(); //!< $_COOKIE counterpart
    private $_files = array(); //!< $_FILES counterpart
   /**@}*/
    
   /**
    * private constructor for the singleton pattern
    */
    private function __construct(){}
    
   /**
    * Instantiates the Request class and transfers $_POST, $_GET, $_COOKIE, and $_FILES superglobals in their respective Request properties.
    *
    * This also strips null bytes from the members of the #$_post, #$_get, and #$_cookie arrays and empties the superglobals mentioned above. Making
    *  the Request class the only way to access these variables
    *
    * @returns the singleton instance of the Request class
    */
    public static function singleton()
    {
      if (self::$_instance !== NULL) {
        return self::$_instance;
      }
      
      $request = new Request();

      $request->_post = $_POST;
      $request->_get = $_GET;
      $request->_cookie = $_COOKIE;
      $request->_files = $_FILES;
      
      // we strip null bytes in the requests
      $toStrip = array(&$request->_post, &$request->_get, &$request->_cookie);
      array_walk_recursive($toStrip, 'indigo\framework\Sanitizer::stripNullBytes');

      // we will not let the user deal with these variables directly
      $_POST = array();
      $_GET = array();
      $_COOKIE = array();
      $_FILES = array();
      
      self::$_instance = $request;

      return self::$_instance;
    }
    
   /**
    * @name Single Value Getter Methods
    * Returns a #$_post, #$_get, or #$_cookie variable of the given key, if exists
    */
   /**@{*/
   
   /**
    * Get a #$_post variable
    * @param $key the key of the variable in one of the arrays
    * @returns The value of the variable, or null if the key is not found
    */
    public function post($key)
    {
      if (isset($this->_post[$key])) {
        return $this->_post[$key];
      }
      else {
        return null;
      }
    }
    
   /**
    * Get a #$_get variable
    * @param $key the key of the variable in the array
    * @returns The value of the variable, or null if the key is not found
    */
    public function get($key)
    {
      if (isset($this->_get[$key])) {
        return $this->_get[$key];
      }
      else {
        return null;
      }
    }
    
   /**
    * Get a #$_cookie variable
    * @param $key the key of the variable in the array
    * @returns The value of the variable, or null if the key is not found
    */
    public function cookie($key)
    {
      if (isset($this->_cookie[$key])) {
        return $this->_cookie[$key];
      }
      else {
        return null;
      }
    }
    
   /**
    * Returns either a #$_post or a #$_get variable of a given key
    *
    * The function first looks for a corresponding key in the #$_post array, then the #$_get array
    */
    public function getVal($key)
    {
      $value = NULL;
      
      $value = $this->_post($key);
      
      if ($value === NULL) {
        $value = $this->_get($key);
      }
        
      return $value;
    }
   /**@}*/
   
   
   /**
    * @name Getter Methods
    * Returns the #$_post, #$_get, or #$_cookie data
    */
   /**@{*/

   /**
    * @returns the #$_post data
    */
		public function postData()
		{
			return $this->_post;
		}
    
   /**
    * @returns the #$_get data
    */
		public function getData()
		{
			return $this->_get;
		}
    
   /**
    * @returns the #$_cookie data
    */
		public function cookieData()
		{
			return $this->_cookie;
		}
    /**@}*/
  }